﻿using Sidvall.Collections;
using System.Linq;

namespace WebOptimizer.Data.Model.EntityManagers
{
	public partial class TaskManager<TEntity, TList>
		where TEntity : global::WebOptimizer.Data.ITask
		where TList : System.Collections.Generic.IEnumerable<global::WebOptimizer.Data.ITask>
	{
		#region Public Members

		#region AcceptChanges

		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1506:AvoidExcessiveClassCoupling"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")]
		public void AcceptChanges(global::WebOptimizer.Data.ITask value)
		{
			if (value == null)
				return;
			if (value.IsDeleted)
				value.SetDataRowContext(null, Sidvall.Data.DataRowState.Added);
			else if (value.IsDirty)
			{
				value.SetDataRowContext(null, Sidvall.Data.DataRowState.Unchanged);
				if (value.Sources != null)
					this.EntityFacadeManager.GenericEntityFacade.SourceManager.AcceptChanges(value.Sources);
			}
		}

		public void AcceptChanges(System.Collections.Generic.IEnumerable<global::WebOptimizer.Data.ITask> value)
		{
			Sidvall.Data.IListContextProvider<ITask> listContextProvider;

			if (value == null)
				return;
			listContextProvider = value as Sidvall.Data.IListContextProvider<ITask>;
			if (listContextProvider != null)
				this.EntityFacadeManager.ResourceManager.Clear(listContextProvider.DeletedItems);
			foreach (var item in value)
				AcceptChanges(item);
		}

		#endregion
		#region LoadInstanceField

		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
		public void LoadInstanceField(System.Collections.Generic.IEnumerable<global::WebOptimizer.Data.ITask> items, string fieldName, object value, bool cascade, bool raisePropertyChanged, bool updateState)
		{
			if (items == null)
				return;
			foreach (var item in items)
				LoadInstanceField(item, fieldName, value, cascade, raisePropertyChanged, updateState);
		}
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
		public void LoadInstanceField(global::WebOptimizer.Data.ITask item, global::WebOptimizer.Data.Fields.TaskField fieldId, object value, bool cascade, bool raisePropertyChanged, bool updateState)
		{
			LoadInstanceField(item, fieldId.ToString(), value, cascade, raisePropertyChanged, updateState);
		}
		partial void OnAfterLoadInstanceField(string fieldName, object value, bool cascade, bool raisePropertyChanged, bool updateState);
		partial void OnBeforeLoadInstanceField(string fieldName, object value, bool cascade, bool raisePropertyChanged, bool updateState);
		partial void OnLoadInstanceField(string fieldName, object value, bool cascade, bool raisePropertyChanged, bool updateState);
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "cascade"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1505:AvoidUnmaintainableCode")]
		public void LoadInstanceField(global::WebOptimizer.Data.ITask item, string fieldName, object value, bool cascade, bool raisePropertyChanged, bool updateState)
		{
			Sidvall.Business.IOnPropertyChanged onPropertyChanged;

			if (item == null)
				return;
			if (fieldName == null)
				return;
			OnBeforeLoadInstanceField(fieldName, value, cascade, raisePropertyChanged, updateState);
			switch (fieldName.ToUpperInvariant())
			{
				case "ISENABLED":
					if (value == null)
						return;
					item.IsEnabled = (bool)value;
					if (raisePropertyChanged)
					{
						onPropertyChanged = item as Sidvall.Business.IOnPropertyChanged;
						if (onPropertyChanged != null)
							onPropertyChanged.OnPropertyChanged("IsEnabled", updateState);
					}
					break;
				case "PATH":
					value = Sidvall.Business.ValidationManager.GetValidString(value, false, null);
					item.Path = value as string;
					if (raisePropertyChanged)
					{
						onPropertyChanged = item as Sidvall.Business.IOnPropertyChanged;
						if (onPropertyChanged != null)
							onPropertyChanged.OnPropertyChanged("Path", updateState);
					}
					break;
				case "TASKID":
					item.TaskId = (System.Nullable<int>)value;
					if (raisePropertyChanged)
					{
						onPropertyChanged = item as Sidvall.Business.IOnPropertyChanged;
						if (onPropertyChanged != null)
							onPropertyChanged.OnPropertyChanged("TaskId", updateState);
					}
					if (cascade)
					{
						if (item.Sources != null)
						{
							this.EntityFacadeManager.GenericEntityFacade.SourceManager.LoadInstanceField(item.Sources, "TaskId", value, cascade, raisePropertyChanged, updateState);
						}
					}
					break;
				case "TASKTYPEID":
					if (value == null)
						return;
					item.TaskTypeId = (global::WebOptimizer.Data.TaskType)value;
					if (raisePropertyChanged)
					{
						onPropertyChanged = item as Sidvall.Business.IOnPropertyChanged;
						if (onPropertyChanged != null)
							onPropertyChanged.OnPropertyChanged("TaskTypeId", updateState);
					}
					break;
				case "SOURCES":
					item.Sources = value as System.Collections.Generic.IEnumerable<global::WebOptimizer.Data.ISource>;
					if (raisePropertyChanged)
					{
						onPropertyChanged = item as Sidvall.Business.IOnPropertyChanged;
						if (onPropertyChanged != null)
							onPropertyChanged.OnPropertyChanged("Sources", updateState);
					}
					if (cascade)
					{
						if (item.Sources != null)
						{
							this.EntityFacadeManager.GenericEntityFacade.SourceManager.LoadInstanceField(item.Sources, "TaskId", item.TaskId, cascade, raisePropertyChanged, updateState);
						}
					}
					break;
				default:
					OnLoadInstanceField(fieldName, value, cascade, raisePropertyChanged, updateState);
					break;
			}
			OnAfterLoadInstanceField(fieldName, value, cascade, raisePropertyChanged, updateState);
		}

		#endregion
		#region Copy

		public TEntity Copy(ITask value)
		{
			return Copy(value, null, string.Empty);
		}
		public TEntity Copy(ITask value, Sidvall.Data.CopySettings copySettings)
		{
			return Copy(value, copySettings, string.Empty);
		}
		internal TEntity Copy(ITask value, Sidvall.Data.CopySettings copySettings, string parent)
		{
			TEntity item;

			if (copySettings == null)
				copySettings = new Sidvall.Data.CopySettings();
			if (!Sidvall.Data.DataRowContextManager.IsValid(value, copySettings.RowFilter))
				return default(TEntity);
			item = (TEntity)this.EntityFacadeManager.ResourceManager.CreateTask(null);
			if (item == null)
				return default(TEntity);
			Import(item, value, copySettings, parent);

			return item;
		}

		public TList Copy(System.Collections.Generic.IEnumerable<ITask> value)
		{
			return Copy(value, null, string.Empty);
		}
		public TList Copy(System.Collections.Generic.IEnumerable<ITask> value, Sidvall.Data.CopySettings copySettings)
		{
			return Copy(value, copySettings, string.Empty);
		}
		internal TList Copy(System.Collections.Generic.IEnumerable<ITask> value, Sidvall.Data.CopySettings copySettings, string parent)
		{
			TList items;

			items = (TList)this.EntityFacadeManager.ResourceManager.CreateTaskCollection();
			Import(items, value, copySettings, parent);

			return items;
		}

		#endregion
		#region GetKey

		public string GetKey(ITask item)
		{
			if (item == null)
				return null;
			if (!item.IsNew)
			{
				item.DataRowKey = null;
				return item.TaskId.ToString();
			}
			if (string.IsNullOrWhiteSpace(item.DataRowKey))
				item.DataRowKey = "New:" + System.Guid.NewGuid().ToString();
			return item.DataRowKey;
		}

		public string GetKey(int taskId)
		{
			return taskId.ToString(System.Globalization.CultureInfo.InvariantCulture);
		}

		#endregion
		#region Import

		public void Import(TEntity destination, ITask source)
		{
			Import(destination, source, null, string.Empty);
		}
		public void Import(TEntity destination, ITask source, Sidvall.Data.CopySettings copySettings)
		{
			Import(destination, source, copySettings, string.Empty);
		}
		partial void OnAfterImport(TEntity destination, ITask source, Sidvall.Data.CopySettings copySettings);
		partial void OnBeforeImport(TEntity destination, ITask source, Sidvall.Data.CopySettings copySettings);
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "parent"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1506:AvoidExcessiveClassCoupling"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
		internal void Import(TEntity destination, ITask source, Sidvall.Data.CopySettings copySettings, string parent)
		{
			if (destination == null)
				return;
			if (source == null)
				return;
			if (copySettings == null)
				copySettings = new Sidvall.Data.CopySettings();
			OnBeforeImport(destination, source, copySettings);
			if ((copySettings.FieldOption & Sidvall.Business.FieldCopyOptions.AutomaticPrimaryKeys) == Sidvall.Business.FieldCopyOptions.AutomaticPrimaryKeys)
			{
				destination.TaskId = source.TaskId;
			}
			if ((copySettings.FieldOption & Sidvall.Business.FieldCopyOptions.ManualNonPrimaryKeys) == Sidvall.Business.FieldCopyOptions.ManualNonPrimaryKeys)
			{
				destination.IsEnabled = source.IsEnabled;
				destination.Path = source.Path;
				destination.TaskTypeId = source.TaskTypeId;
			}
			switch (copySettings.ChildrenOption)
			{
				case Sidvall.Data.MergeOption.DoNothing:
					break;
				case Sidvall.Data.MergeOption.Replace:
					break;
				default:
					if (parent != "Source")
					{
						if (destination.Sources != null)
							this.EntityFacadeManager.GenericEntityFacade.SourceManager.Import(destination.Sources, source.Sources, copySettings, "Task");
						else if (source.Sources != null)
							destination.Sources = this.EntityFacadeManager.GenericEntityFacade.SourceManager.Copy(source.Sources, copySettings, "Task");
					}
					break;
			}
			switch (copySettings.ParentOption)
			{
				case Sidvall.Data.MergeOption.DoNothing:
					break;
				case Sidvall.Data.MergeOption.Replace:
					break;
				default:
					break;
			}
			if (copySettings.IncludeDataRowContext)
			{
				if (source.IsNew)
					GetKey(source);
				destination.SetDataRowContext(source, copySettings.DataRowState);
			}
			else if (copySettings.DataRowState != null)
				destination.SetDataRowContext(null, copySettings.DataRowState);
			OnAfterImport(destination, source, copySettings);
		}

		public void Import(TList destination, System.Collections.Generic.IEnumerable<ITask> source)
		{
			Import(destination, source, null, string.Empty);
		}
		public void Import(TList destination, System.Collections.Generic.IEnumerable<ITask> source, Sidvall.Data.CopySettings copySettings)
		{
			Import(destination, source, copySettings, string.Empty);
		}
		public void Import(TList destination, Sidvall.Data.FetchListResponse<ITask> source, Sidvall.Data.CopySettings copySettings)
		{
			Sidvall.Data.ITotalRowCount totalRowCount;

			if (source == null)
				return;
			Import(destination, source.Items, copySettings, string.Empty);
			if (source.TotalRowCount != null)
			{
				totalRowCount = destination as Sidvall.Data.ITotalRowCount;
				if (totalRowCount != null)
					totalRowCount.TotalRowCount = source.TotalRowCount.Value;
			}
		}
		partial void OnBeforeImport(TList destination, System.Collections.Generic.IEnumerable<ITask> source, Sidvall.Data.CopySettings copySettings);
		partial void OnAfterImport(TList destination, System.Collections.Generic.IEnumerable<ITask> source, Sidvall.Data.CopySettings copySettings);
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
		internal void Import(TList destination, System.Collections.Generic.IEnumerable<ITask> source, Sidvall.Data.CopySettings copySettings, string parent)
		{
			System.Collections.Generic.Dictionary<string, ITask> index;
			Sidvall.Collections.ISupportsListChangedEvents supportsListChangedEvents;
			Sidvall.Data.IListContextProvider<ITask> destinationListContextProvider, sourceListContextProvider;
			Sidvall.Data.ITotalRowCount destinationTotalRowCount, sourceTotalRowCount;
			System.Collections.Generic.List<ITask> deletedItems;
			ITask item;
			string key;

			if (destination == null)
				return;
			if (source == null)
				return;
			if (!source.Any())
				return;
			if (copySettings == null)
				copySettings = new Sidvall.Data.CopySettings();
			else if (copySettings.MergeOption == Sidvall.Data.MergeOption.DoNothing)
				return;
			
			OnBeforeImport(destination, source, copySettings);
			supportsListChangedEvents = destination as Sidvall.Collections.ISupportsListChangedEvents;
			if (supportsListChangedEvents != null)
				supportsListChangedEvents.RaiseListChangedEvents = false;
			switch (copySettings.MergeOption)
			{
				case Sidvall.Data.MergeOption.UpdateOnKey:
					index = destination.ToDictionary(GetKey, true);
					foreach (var sourceItem in source)
					{
						key = GetKey(sourceItem);
						if (index.ContainsKey(key))
						{
							item = index[key];
							Import((TEntity)item, sourceItem, copySettings, parent);
						}
					}
					break;
				case Sidvall.Data.MergeOption.MergeOnKey:
					index = destination.ToDictionary(GetKey, true);
					foreach (var sourceItem in source)
					{
						key = GetKey(sourceItem);
						if (index.ContainsKey(key))
						{
							item = index[key];
							Import((TEntity)item, sourceItem, copySettings, parent);
						}
						else
						{
							item = Copy(sourceItem, copySettings, parent);
							if (item != null)
							{
								if (copySettings.IncludeDataRowContext)
									item.DataRowKey = GetKey(sourceItem);
								this.EntityFacadeManager.ResourceManager.Add(destination, item);
							}
						}
					}
					break;
				case Sidvall.Data.MergeOption.MergeOnKeyAndState:
					index = source.ToDictionary(GetKey, true);
					deletedItems = new System.Collections.Generic.List<ITask>();
					foreach (var destinationItem in destination)
					{
						if (!Sidvall.Data.DataRowContextManager.IsValid(destinationItem, copySettings.RowFilter))
							continue;
						key = GetKey(destinationItem);
						if (index.ContainsKey(key))
						{
							item = index[key];
							Import((TEntity)destinationItem, item, copySettings, parent);
						}
						else
						{
							deletedItems.Add(destinationItem);
						}
					}
					foreach (var deletedItem in deletedItems)
						this.EntityFacadeManager.ResourceManager.Remove(destination, deletedItem);
					break;
				case Sidvall.Data.MergeOption.Replace:
					break;
				default:
					foreach (var sourceItem in source)
					{
						item = Copy(sourceItem, copySettings, parent);
						if (item != null)
						{
							if (copySettings.IncludeDataRowContext)
								item.DataRowKey = GetKey(sourceItem);
							this.EntityFacadeManager.ResourceManager.Add(destination, item);
						}
					}
					if ((copySettings.RowFilter & Sidvall.Data.DataRowFilters.Deleted) == Sidvall.Data.DataRowFilters.Deleted)
					{
						sourceListContextProvider = source as Sidvall.Data.IListContextProvider<ITask>;
						if (sourceListContextProvider != null)
						{
							destinationListContextProvider = destination as Sidvall.Data.IListContextProvider<ITask>;
							foreach (var sourceItem in sourceListContextProvider.DeletedItems)
							{
								item = Copy(sourceItem, copySettings, parent);
								if (destinationListContextProvider != null)
									this.EntityFacadeManager.ResourceManager.Add(destinationListContextProvider.DeletedItems, item);
								else
									this.EntityFacadeManager.ResourceManager.Add(destination, item);
							}
						}
					}
					break;
			}
			if (supportsListChangedEvents != null)
				supportsListChangedEvents.RaiseListChangedEvents = true;
			sourceTotalRowCount = source as Sidvall.Data.ITotalRowCount;
			if (sourceTotalRowCount != null)
			{
				destinationTotalRowCount = destination as Sidvall.Data.ITotalRowCount;
				if (destinationTotalRowCount != null)
					destinationTotalRowCount.TotalRowCount = sourceTotalRowCount.TotalRowCount;
			}
			OnAfterImport(destination, source, copySettings);
		}

		#endregion
		#region IsBusy

		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1506:AvoidExcessiveClassCoupling"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
		public bool IsBusy(ITask value)
		{
			Sidvall.Data.IBusyParentProvider busy;

			if (value == null)
				return false;
			busy = value as Sidvall.Data.IBusyParentProvider;
			if ((busy != null) && (busy.IsSelfBusy))
				return true;
			if ((value.Sources != null) && (this.EntityFacadeManager.GenericEntityFacade.SourceManager.IsBusy(value.Sources)))
				return true;
			return false;
		}

		public bool IsBusy(System.Collections.Generic.IEnumerable<ITask> value)
		{
			Sidvall.Data.IListContextProvider<ITask> listContextProvider;

			if (value == null)
				return false;
			foreach (var item in value)
			{
				if (IsBusy(item))
					return true;
			}
			listContextProvider = value as Sidvall.Data.IListContextProvider<ITask>;
			if ((listContextProvider != null) && (listContextProvider.DeletedItems != null))
			{
				foreach (var item in listContextProvider.DeletedItems)
				{
					if (IsBusy(item))
						return true;
				}
			}
			return false;
		}

		#endregion
		#region IsDirty

		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1506:AvoidExcessiveClassCoupling"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
		public bool IsDirty(ITask value)
		{
			if (value == null)
				return false;
			if (value.IsSelfDirty)
				return true;
			if ((value.Sources != null) && (this.EntityFacadeManager.GenericEntityFacade.SourceManager.IsDirty(value.Sources)))
				return true;
			return false;
		}

		public bool IsDirty(System.Collections.Generic.IEnumerable<ITask> value)
		{
			Sidvall.Data.IListContextProvider<ITask> listContextProvider;

			if (value == null)
				return false;
			listContextProvider = value as Sidvall.Data.IListContextProvider<ITask>;
			if ((listContextProvider != null) && (listContextProvider.DeletedItems.Any()))
				return true;
			foreach (var item in value)
			{
				if (IsDirty(item))
					return true;
			}
			return false;
		}

		#endregion
		#region Validate

		public Sidvall.Data.BrokenRuleCollection Validate(ITask value)
		{
			return Validate(value, null);
		}
		partial void OnBeforeValidate(ITask value, Sidvall.Data.ValidationSettings settings, Sidvall.Data.BrokenRuleCollection rules);
		partial void OnAfterValidate(ITask value, Sidvall.Data.ValidationSettings settings, Sidvall.Data.BrokenRuleCollection rules);
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1506:AvoidExcessiveClassCoupling")]
		public Sidvall.Data.BrokenRuleCollection Validate(ITask value, Sidvall.Data.ValidationSettings settings)
		{
			Sidvall.Data.BrokenRuleCollection rules;

			rules = new Sidvall.Data.BrokenRuleCollection();
			if (value == null)
				return rules;
			if (settings == null)
				settings = new Sidvall.Data.ValidationSettings();
			OnBeforeValidate(value, settings, rules);
			if (settings.ValidateProperties)
			{
				value.Path = Sidvall.Business.ValidationManager.GetValidString(value.Path, false, null);
			}
			if (settings.ValidateChildren)
			{
				if (value.Sources != null)
					this.EntityFacadeManager.GenericEntityFacade.SourceManager.Validate(value.Sources, settings);
			}
			OnAfterValidate(value, settings, rules);
			
			return rules;
		}
		public Sidvall.Data.BrokenRuleCollection Validate(System.Collections.Generic.IEnumerable<ITask> value)
		{
			return Validate(value, null);
		}
		public Sidvall.Data.BrokenRuleCollection Validate(System.Collections.Generic.IEnumerable<ITask> value, Sidvall.Data.ValidationSettings settings)
		{
			Sidvall.Data.BrokenRuleCollection rules, childRules;

			rules = new Sidvall.Data.BrokenRuleCollection();
			if (value == null)
				return rules;
			foreach (var item in value)
			{
				childRules = Validate(item, settings);
				rules.Import(childRules);
			}
			return rules;
		}

		#endregion
		#region InitializeDefaultValues

		partial void OnAfterInitializeDefaultValues(ITask value);
		partial void OnBeforeInitializeDefaultValues(ITask value);
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
		public void InitializeDefaultValues(ITask value)
		{
			if (value == null)
				return;
			OnBeforeInitializeDefaultValues(value);
			value.IsEnabled = false;
			value.Path = string.Empty;
			value.TaskId = null;
			value.TaskTypeId = global::WebOptimizer.Data.TaskType.CompressJavaScript;
			OnAfterInitializeDefaultValues(value);
		}

		#endregion

		#endregion
		#region Private Members

		private global::WebOptimizer.Data.Model.IEntityFacadeManager EntityFacadeManager { get; set; }

		#endregion
		#region Constructors

		public TaskManager(global::WebOptimizer.Data.Model.IEntityFacadeManager entityFacadeManager)
		{
			this.EntityFacadeManager = entityFacadeManager;
		}

		#endregion
	}
}